﻿namespace System
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Threading;
    /// <summary>
    /// 任务运行器
    /// </summary>

    public class AsyncActionRunner
    {
        private readonly IEnumerator<IAsyncAction> _enumerator;
        private EventHandler _Completed;
        private int index;
        private EventHandler<ProgressEventArgs> _ProgressChanged;
        private int taskCount;
        /// <summary>
        /// 完成事件及处理方法
        /// </summary>
        public event EventHandler Completed
        {
            add
            {
                EventHandler handler2;
                EventHandler completed = this._Completed;
                do
                {
                    handler2 = completed;
                    EventHandler handler3 = (EventHandler) Delegate.Combine(handler2, value);
                    completed = Interlocked.CompareExchange<EventHandler>(ref this._Completed, handler3, handler2);
                }
                while (completed != handler2);
            }
            remove
            {
                EventHandler handler2;
                EventHandler completed = this._Completed;
                do
                {
                    handler2 = completed;
                    EventHandler handler3 = (EventHandler) Delegate.Remove(handler2, value);
                    completed = Interlocked.CompareExchange<EventHandler>(ref this._Completed, handler3, handler2);
                }
                while (completed != handler2);
            }
        }
        /// <summary>
        /// 进度发生更改时发生
        /// </summary>

        public event EventHandler<ProgressEventArgs> ProgressChanged
        {
            add
            {
                EventHandler<ProgressEventArgs> handler2;
                EventHandler<ProgressEventArgs> progressChanged = this._ProgressChanged;
                do
                {
                    handler2 = progressChanged;
                    EventHandler<ProgressEventArgs> handler3 = (EventHandler<ProgressEventArgs>) Delegate.Combine(handler2, value);
                    progressChanged = Interlocked.CompareExchange<EventHandler<ProgressEventArgs>>(ref this._ProgressChanged, handler3, handler2);
                }
                while (progressChanged != handler2);
            }
            remove
            {
                EventHandler<ProgressEventArgs> handler2;
                EventHandler<ProgressEventArgs> progressChanged = this._ProgressChanged;
                do
                {
                    handler2 = progressChanged;
                    EventHandler<ProgressEventArgs> handler3 = (EventHandler<ProgressEventArgs>) Delegate.Remove(handler2, value);
                    progressChanged = Interlocked.CompareExchange<EventHandler<ProgressEventArgs>>(ref this._ProgressChanged, handler3, handler2);
                }
                while (progressChanged != handler2);
            }
        }

        public AsyncActionRunner()
        {
            this.taskCount = 0;
            this.index = 1;
        }

        public AsyncActionRunner(IList<IAsyncAction> tasks) : this()
        {
            this.taskCount = tasks.Count<IAsyncAction>();
            this._enumerator = tasks.GetEnumerator();
            this.TaskResults = new List<ActionResult>(this.taskCount);
        }

        public AsyncActionRunner(params IAsyncAction[] tasks) : this(tasks.ToList<IAsyncAction>())
        {
        }
        /// <summary>
        /// 执行所有任务
        /// </summary>

        public void Execute()
        {
            if (this._enumerator.MoveNext())
            {
                IAsyncAction current = this._enumerator.Current;
                this.TaskResults.Add(current.ActionResult);
                int ci = this.index++;
                current.Completed += delegate (object sender, EventArgs args) {
                    ActionResult result = ((IAsyncAction) sender).ActionResult;
                    result.EndTime = DateTime.Now;
                    if (this._ProgressChanged != null)
                    {
                        this._ProgressChanged(this, new ProgressEventArgs(ci, this.TaskCount, ((double) ci) / ((double) this.taskCount), result));
                    }
                    this.Execute();
                };
                current.PreActionResult = (ci > 1) ? this.TaskResults[ci - 2] : null;
                current.ActionResult.Status = ActionStatus.Running;
                current.ActionResult.StartTime = DateTime.Now;
                current.Execute();
                if (this._ProgressChanged != null)
                {
                    this._ProgressChanged(this, new ProgressEventArgs(ci, this.TaskCount, (ci - 1.0) / ((double) this.taskCount), current.ActionResult));
                }
            }
            else
            {
                this.index = 1;
                EventHandler completed = this._Completed;
                if (completed != null)
                {
                    completed(this, EventArgs.Empty);
                }
            }
        }

        public int TaskCount
        {
            get
            {
                return this.taskCount;
            }
        }
        /// <summary>
        /// 保存所有任务的执行结果
        /// </summary>
        public List<ActionResult> TaskResults { get; private set; }
    }
}

